<?php

namespace App\Models\Store;

use App\Models\Admin\StoreAdmin;
use App\Models\Concerns\ScopeFilterable;
use App\Models\Concerns\YouzanAuthorizerable;
use App\Models\Customer\Banner;
use App\Models\Customer\Bannerable;
use App\Models\Customer\Customer;
use App\Models\Customer\DeviceAccount;
use App\Models\OpenWechat\Authorizer;
use App\Models\OpenWechat\WechatUser;
use App\Models\Order;
use App\Models\Panx\Product;
use App\Models\Panx\Record;
use App\Models\Panx\SkinRecordBonus;
use App\Models\Youzan\YouzanAuthorizer;
use App\Observers\BosCleanObserver;
use App\Services\BaiduGeoService\MapApi;
use App\Services\Utils\Bosable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Foundation\Auth\User as Authenticatable;

use Illuminate\Support\Facades\DB;
use Tymon\JWTAuth\Contracts\JWTSubject as AuthenticatableUserContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;

/**
 * @property int id
 * @property string name
 * @property int is_deleted
 * @property int customer_id
 * @property string youzan_authorizer_id
 * @property string province
 * @property string city
 * @property string district
 * @property string address
 *
 * @property-read Customer customer
 * @property-read YouzanAuthorizer youzanAuthorizer
 * @property-read Collection storeAdmins
 * @property-read DeviceAccount[]|Collection deviceAccounts
 * @property-write StoreAdmin admin
 * @property-write Collection|StoreAdmin[] staffs
 * @property-write int hm_skin_count - 对应指定微信用户在该店使用接触测肤次数
 * @property-write int all_skin_count - 对应指定微信用户在该店总测肤次数
 * @property-write int wax_skin_count - 对应指定微信用户在该店使用图像测肤次数
 *
 * @mixin  Builder
 */
class Store extends Model implements YouzanAuthorizerable
{
    use Bosable;
    use ScopeFilterable;

    const IS_NOT_DELETED = 0; // 店家 启用
    const IS_DELETED = 1;    // 店家 禁用

    const HAS_YOUZAN = 1;    // 开通有赞
    const NO_YOUZAN = 0;     // 没有开通有赞

    const TYPE_MAIN_STORE = 1;   // 总店
    const TYPE_BRANCH_STORE = 2; // 分店

    public $bos_columns = ['store_img'];

    protected $store_img_bos_key_prefix = 'store/store_img/';

    protected static $unguarded = true;

    protected $table = 'stores';

    protected $hidden = ['password'];

    protected $casts = [
        'is_deleted'  => 'int',
        'phone'       => 'string',
        'type'        => 'int',
        'customer_id' => 'int',
    ];

    /**
     * @param $store_id
     * @param int $count
     * @return mixed
     */
    public static function incrementVisitById($store_id, $count = 1)
    {
        return (new self)->where('id', $store_id)
            ->increment('visit', $count);
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany|StoreAdmin
     */
    public function storeAdmins()
    {
        return $this->hasMany(StoreAdmin::class, 'store_id', 'id');
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo|YouzanAuthorizer
     */
    public function youzanAuthorizer()
    {
        return $this->belongsTo(YouzanAuthorizer::class);
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany|StoreAdmin
     */
    public function storeStaffs()
    {
        /** @var \Illuminate\Database\Eloquent\Relations\HasMany|StoreAdmin $staff */
        $staff = $this->hasMany(StoreAdmin::class, 'store_id', 'id');

        return $staff->role(StoreAdmin::STAFF);
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function pack()
    {
        return $this->hasOne(Pack::class, 'store_id', 'id');
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
     */
    public function appBanners()
    {
        return $this->morphToMany(Bannerable::class, 'bannerable');
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
     */
    public function banners()
    {
        return $this->morphToMany(Banner::class, 'bannerable');
    }

    public function getJWTIdentifier()
    {
        return $this->getKey(); // Eloquent model method
    }

    /**
     * @return array
     */
    public function getJWTCustomClaims()
    {
        return [];
    }

    public function customer(): BelongsTo
    {
        return $this->belongsTo(Customer::class);
    }

    public function getAuthorizer(): ?Authorizer
    {
        /** @var Authorizer $authorizer */
        $authorizer = $this->customer
            ->authorizer()
            ->where('canceled', Authorizer::STATUS_AUTH)
            ->first();
        
        return $authorizer ?: null;
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function getProducts()
    {
        return $this->hasMany(Product::class, 'store_id', 'id')
            ->where('is_sale', Product::IS_SALE)
            ->where('is_deleted', Product::IS_NO_DELETE);
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\hasMany|Product
     *
     */
    public function products()
    {
        return $this->hasMany(Product::class, 'store_id', 'id');
    }

    /**
     * 店铺同步的有赞商品，产生的订单。
     *
     * @return Builder|\Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function orders()
    {
        return $this->hasMany(Order::class, 'store_id', 'id')
            ->where('product_belong_to', Order::PRODUCT_BELONG_TO_STORE);
    }

    /**
     * @see \App\Http\Controllers\Youzan\OAuthController::updateYouzanProductsAndOrders
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function selfProducts()
    {
        return $this->products();
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany|Product
     */
    public function customerProducts()
    {
        return $this->belongsToMany(Product::class, 'store_pivot_customer_product', 'store_id','product_id');
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany|WechatUser
     */
    public function wechatUsers()
    {
        return $this
            ->belongsToMany(
            WechatUser::class, 'store_pivot_wechat_user',
            'store_id', 'wechat_user_id'
            )
            ->withTimestamps();
    }

    /**
     * @param $store_img
     * @throws \Exception
     */
    public function setStoreImgAttribute($store_img)
    {
        if (is_file($store_img)) {
            $this->attributes['store_img'] = $this->uploadPostFile($store_img , $this->store_img_bos_key_prefix);
        }
    }

    /**
     * @return mixed|null
     */
    public function getStoreImgAttribute()
    {
        if (! $this->attributes['store_img']) return null;

        return $this->getStaticUrl($this->attributes['store_img']);
    }
    
    public function skinRecords()
    {
        return $this->hasMany(SkinRecord::class, 'store_id', 'id');
    }

    public function deviceAccounts()
    {
        return $this->hasMany(DeviceAccount::class, 'store_id', 'id');

    }

    /**
     * lyun 命名没有反映出函数的目的与行为，以后不要出现这种命名
     *
     * 前端在 商家 Banner 管理中已使用 get_device_accounts，所以暂时不修改
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function getDeviceAccounts()
    {
        return $this->deviceAccounts()->select(['id', 'store_id', 'account', 'device_name']);
    }

    /**
     * 注册删除 bosKey 事件绑定
     */
    protected static function boot()
    {
        parent::boot();

        /*
         * 监听bos清理事件
         */
        self::observe(BosCleanObserver::class);
    }

    /**
     * @deprecated
     */
    /*public function getTryOnAttribute()
    {
        $device_account_ids = (new DeviceAccount())->where('store_id',$this->id)->pluck('id');
        return DB::table('records')
            ->whereIn('recorderable_id',$device_account_ids)
            ->where([
                ['recorderable_type',class_basename(DeviceAccount::class)],
                ['objectable_type',class_basename(Product::class)],
                ['record_type_id',Record::TRY_ON],
            ])
            ->count();
    }

    public function getSkinRecordCountAttribute()
    {
        return (new SkinRecord)->where('store_id',$this->id)->count();
    }*/

    /**
     * @param $address
     *
     * @return array|null
     *
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public static function queryAddressLocation(string $address): ?array
    {
        $geo_service = new MapApi();

        $res = $geo_service->getLocationQuery($address);
        if ($res['status'] === MapApi::RESPONSE_STATUS_OK) {
            return [
                'longitude' => $res['result']['location']['lng'],
                'latitude' => $res['result']['location']['lat'],
            ];
        } else {
            return null;
        }
    }

}
